#include "mainserver.h"

#include <boost/bind.hpp>



// prepositions "FROM" and "TO" refer to the client.
// as in: connection FROM CLIENT
// and connection TO CLIENT



mainServer::mainServer(const std::string& address, int port) : 
  LoggingService("SERVER"),
  // initialize boost stuff
  m_io_service(),
  m_mgr(m_io_service)
{
  // create tcpip resolver
  tcp::resolver res(m_io_service);

 

  m_connection_name[0] = "from";
  m_connection_name[1] = "to";


  // 0 -- user connection from
  // 1 -- user connection to
  for (int i = 0; i < 2; i++)
  {
    info() << "initializing acceptor[" << i << "] on port " << port+i << " for connection " << m_connection_name[i] << endl;

    m_acceptor[i] = new tcp::acceptor(m_io_service);

    char port_char[10];
    std::string port_s;

    // query to resolve name
    // this is embarrasing
    sprintf(port_char, "%d", port+i);
    port_s = port_char;
    tcp::resolver::query query(address, port_s);

    // create endpoint
    tcp::endpoint endpoint = *res.resolve(query);
    // open up a tcpip connection acceptor 
    m_acceptor[i]->open(endpoint.protocol() );
    
    m_acceptor[i]->set_option(tcp::acceptor::reuse_address(true)); 

    m_acceptor[i]->bind(endpoint);

    debug() << "opened asio acceptor" << endl;

    m_acceptor[i]->listen();

    // listen for user connection id i
    begin_listen(i);
  }
}


void mainServer::begin_listen(int index)
{
//  boost::shared_ptr<tcp::socket> socket(new tcp::socket(m_io_service));
  boost::shared_ptr<tcp::socket> socket(new tcp::socket(m_io_service));

  info() << "listening for a new connection " << m_connection_name[index] << endl;

  m_acceptor[index]->async_accept(
    *(socket.get()),
    boost::bind(
          &mainServer::handle_accept, 
          this, 
          boost::asio::placeholders::error, 
          socket,
          index
        )
      );
}


void mainServer::run()
{
  // by this time, we have scheduled to accept a new connection in m_io_service. 
  m_io_service.run();

  fatal() << "mainServer.io_service stopped!!" << endl;
  //sleep(10);
}

void mainServer::stop()
{
  // fancy asio any-thread stop call
  m_io_service.post(
    boost::bind(&mainServer::handle_stop, this)
      );
}

void mainServer::handle_stop()
{
  // stop accepting new connections
  info() << "closing asio acceptor..." << endl;

  for (int i = 0; i < 2; i++)
  {
    m_acceptor[i]->close();
  }

  m_io_service.stop();
  m_io_service.reset();

  // close all active connections
  info() << "closing active connections..." << std::endl;
//  m_mgr.closeAll();
}

void mainServer::handle_accept(const boost::system::error_code &e, boost::shared_ptr<tcp::socket> socket, int index) 
{
  if (!e)
  {
    info() << "accepted new connection. registering with userconnmgr" << endl;

    bool direction = (index == 0);
    m_mgr.registerUserSocket(socket, direction);

    begin_listen(index);
  }
  else
  {
    fatal() << "error in handle_accept." << e << endl;
  }


}


mainServer::~mainServer()
{
  for (int i = 0; i < 2; i ++)
  {
    delete m_acceptor[i];
  }
}

